﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace LightCAD.Core.Elements
{
    public class LcCurve2d : LcElement
    {
        public  Curve2d Curve ;
        public override LcElement Clone()
        {
            var curve = new LcCurve2d();
            curve.Copy(this);
            return curve;
        }
        public override void Copy(LcElement src)
        {
            base.Copy(src);
            this.Curve.Copy((src as LcCurve2d).Curve);
        }
        public override Curve2d GetCurve()
        {
            return  this.Curve  ;
        }
        public override Curve2d[] GetCurves()
        {
            return new Curve2d[] { this.Curve };
        }
        public override void Translate(Vector2 vec)
        {
            this.Curve.Translate(vec);
            if (this._boudingBox != null)
                this._boudingBox.Translate(vec);
        }
        public override void Translate(double dx, double dy)
        {
            this.Curve.Translate(dx, dy);
            if (this._boudingBox != null)
                this._boudingBox.Translate(dx, dy);
        }
        public override void Move(Vector2 startPoint, Vector2 endPoint)
        {
            var offset = new Vector2(endPoint.X - startPoint.X, endPoint.Y - startPoint.Y);
            this.Curve?.Translate(offset);
            if (this._boudingBox != null)
                this._boudingBox.Translate(offset);
        }
        public override void Mirror(Vector2 axisStart, Vector2 axisEnd)
        {
            var axisDir = new Vector2().SubVectors(axisEnd, axisStart).Normalize();
            this.Curve.Mirror(axisStart, axisDir);
            this.ResetBoundingBox();
        }
        public override void Rotate(Vector2 basePoint, double rotateAngle)
        {
            this.Curve.RotateAround(basePoint, rotateAngle);
            this.ResetBoundingBox();
        }
        public override LcElement ApplyMatrix(Matrix3 matrix)
        {
            this.Curve.ApplyMatrix(matrix);
            this.ResetBoundingBox();
            return this;
        }
        public override Box2 GetBoundingBox()
        {
            return new Box2().SetFromPoints( this.Curve.GetPoints(-1));
        }
        public override Box2 GetBoundingBox(Matrix3 matrix)
        {
            return new Box2().SetFromPoints(this.Curve.GetPoints(-1).Select(p=>p.ApplyMatrix3(matrix)).ToArray());
        }
        public override bool IncludedByBox(Polygon2d testPoly, List<RefChildElement> includedChildren = null)
        {
            return testPoly.BoundingBox.ContainsBox(this.BoundingBox)&& this.Curve.GetPoints().All(p => GeoUtils.IsPointInPolygon(p, testPoly.Points));
        }
        public override bool IntersectWithBox(Polygon2d testPoly, List<RefChildElement> intersectChildren = null)
        {
            if (testPoly.BoundingBox.IntersectsBox(this.BoundingBox))
            {
                if(testPoly.BoundingBox.ContainsBox(this.BoundingBox))
                    return true;
                var size = Math.Max(testPoly.BoundingBox.Width, testPoly.BoundingBox.Height);
                var scale = size / 500;
                var points = this.Curve.GetPoints(-1, scale);
                for (var i = 0; i < points.Length; i++)
                {
                    var ni = i + 1;
                    if (ni == points.Length)
                        ni = 0;
                    if (GeoUtils.IsPolygonIntersectLine(testPoly.Points, points[i], points[ni]))
                        return true;
                }
                return false;
            }
            return false;
        }

    }
}
